/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ClassChooser.java
 *
 * Created on 2008-12-06, 04:02:25
 */
package pl.put.dcs_modeler.visualModelEditor.propertiesEditor.propertyEditorsForClasses.classPathPropertyEditor;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.JPanel;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.text.Position.Bias;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectInformation;
import org.netbeans.api.project.ProjectUtils;
import org.netbeans.spi.project.support.ProjectOperations;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;

/**
 *
 * @author LukaszR
 */
public class ClassChooser extends JPanel
{
    public static final String PACKAGE_SEPARATOR = ".";
    public static Logger log = Logger.getLogger( ClassChooser.class.getName() );
    private String selectedClass;
    private Project project;
    private DefaultTreeModel model;

    /** Creates new form ClassChooser */
    public ClassChooser( Project project )
    {
        //create the top node
        this.project = project;

        if ( project != null )
        {
            createTreeModel(); // towrzenie poczatkowego modelu drzewa. Przy tworzeniu property editor jest
        }
        initComponents();
        log.info( "Kontruktor ClassChooser");
        

        jTree1.addTreeWillExpandListener( new TreeWillExpandListener() {

            @Override
            public void treeWillExpand( TreeExpansionEvent event ) throws ExpandVetoException
            {
                log.info( "will expanse " + event.getPath() );
                TreePath path = event.getPath();
                expanseTree( path );
            }

            @Override
            public void treeWillCollapse( TreeExpansionEvent event ) throws ExpandVetoException
            {

            }
        } );

        jTree1.addTreeSelectionListener( new TreeSelectionListener()
        {

            @Override
            public void valueChanged( TreeSelectionEvent e )
            {
                Object[] partPath = e.getNewLeadSelectionPath().getPath();
                String path = getProject().getProjectDirectory() + File.separator;
                String relativePath = "";
                int i = 0;
                int lastElement = partPath.length - 1;
                for ( Object tmp : partPath )
                {
                    if ( i != 0 )
                    {
                        path += ( ( DefaultMutableTreeNode )tmp ).getUserObject();
                        if ( i < lastElement )
                        {
                            path += File.separator;
                        }
                    }

                    if ( i > 1 )
                    {            
                        if ( i < lastElement )
                        {
                            relativePath += ( ( DefaultMutableTreeNode )tmp ).getUserObject();
                            relativePath += PACKAGE_SEPARATOR;
                        }
                        else
                        {
                            File f = new File( path );
                            if ( f.isFile() )
                            {
                                String javaFile = ( String )( ( DefaultMutableTreeNode )tmp ).getUserObject();
                                log.info( "java file: " + javaFile );
                                int dotPos = javaFile.lastIndexOf( '.' );
                                javaFile = javaFile.substring( 0, dotPos );
                                log.info( "java file2: " + javaFile );
                                relativePath += javaFile; // przedostatni element, zeby pozbyc sie czesci ".java"
                            }
                            else
                            {
                                relativePath = "";
                            }
                        }
                    }
                    i++;
                }
               
                File f = new File( path );
                log.info( "path2: " + path );
                
               
                if ( ( getSelectedClass() != null ) && f.isFile() )
                {
                    selectedClass = relativePath;
                    firePropertyChange( "selectedClass", "ggg", relativePath );
                }

                
                
                // czynnosci dla rozwiniecia drzewa
                //TreePath path = e.getNewLeadSelectionPath();
                //expanseTree( path );
            }
        } );
        
    }

    private void expanseTree( TreePath path )
    {
        if ( path == null )
        {
            return;
        }
        DefaultMutableTreeNode curNode = ( DefaultMutableTreeNode )path.getLastPathComponent();
        Object nodes[] = path.getPath();
        String dir = "";
        for ( int i = 1; i < nodes.length; i++ )
        {
            DefaultMutableTreeNode node = ( DefaultMutableTreeNode )nodes[i];
            //the user object will hold the directory name
            dir += ( String )node.getUserObject();
            //add the platform independent directory separator character
            dir += File.separator;
        }
        //add the sub directory nodes to the selected one
        addChildren( curNode, getProject().getProjectDirectory() + File.separator + dir );

        //refresh the GUI
        
        repaint();
    }

    protected void addChildren( MutableTreeNode node, String path )
    {
        //create filter for directories only
        DirectoryFileFilter filter = new DirectoryFileFilter();
        //get directories
        File dir = new File( path );
        if ( dir.isDirectory() )
        {

            File subDirs[] = dir.listFiles( filter );
            
            //add sub nodes to given nodes
            if ( subDirs != null )
            {

                if ( node.getChildCount() > 0 )
                {                    
                    node.remove( 0 ); // wywalamy fake-owy elemnt (patrz nizej na opis)

                }
                int i = 0;
                for ( File f : subDirs )
                {
                    MutableTreeNode child = new DefaultMutableTreeNode( f.getName() );
                    // zeby sie pokazal znak rozwijania przy folderze musimy dodac choc jeden pusty subnode. Pozniej przy rozwinieciu go usuwamy.
                    if ( f.isDirectory() )
                    {
                        MutableTreeNode fakeChild = new DefaultMutableTreeNode( "hhh" );
                        child.insert( fakeChild, 0 );
                    }
                    node.insert( child, i++ );
                }
            }
        }
    }

    private void createTreeModel()
    {
        ProjectInformation projInfo = ProjectUtils.getInformation( project );

        MutableTreeNode root = new DefaultMutableTreeNode( projInfo.getDisplayName() );
        List< FileObject > projSrc = ProjectOperations.getDataFiles( project );
        int i = 0;
        for ( FileObject fo : projSrc )
        {
            DefaultMutableTreeNode node = new DefaultMutableTreeNode( fo.getName() );
            if ( fo.isFolder() )
            {
                MutableTreeNode fakeChild = new DefaultMutableTreeNode( "test" );
                node.insert( fakeChild, 0 );
            }
            root.insert( node, i++ );

        }

        

        model = new DefaultTreeModel( root );



    }

    /**
     * Zanzacza na drzewie podana wartosc (przekazana, jako parametr).
     */
    private void setTreeValue()
    {
        log.info( "setTreeValue");
        if ( selectedClass != null )
        {
            // poszukujemy w jakim katalogu jest dany plik. Zakladmay,ze nie moze byc wiele kopii tej samej klasy w jednym pakiecie
            List< FileObject > projSrcList = ProjectOperations.getDataFiles( project );

            String path = selectedClass.replace( '.', File.separator.charAt( 0 ) );
            String src = "";
            log.info(  "set PAth: " + path );
            int i = 0;
            for ( FileObject fo : projSrcList )
            {
                String absPath = fo.getPath() + File.separator + path + ".java";
                log.info(  "path setTreeValue:" + absPath );
                File f = new File( absPath );
                if ( f.isFile() )
                {
                    src = fo.getName();
                    break;
                }
                
            }
            log.info( "src:" + src );
            if ( !src.equals( "" ) )
            {
                TreePath node = jTree1.getNextMatch( src, 0, Bias.Forward );
                log.info( "node:" + node.getPath() );
                jTree1.collapsePath( node );
            }
        }
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings( "unchecked" )
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();

        jTree1.setModel(model);
        jTree1.setAutoscrolls(true);
        jScrollPane1.setViewportView(jTree1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 426, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(12, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTree jTree1;
    // End of variables declaration//GEN-END:variables

    public String getSelectedClass()
    {
        return this.selectedClass;
    }

    public void setSelectedClass( String classPath )
    {
        log.info(  "------------------------------------------: " + classPath );
        this.selectedClass = classPath;
        //setTreeValue();
        
    }

    public Project getProject()
    {
        return project;
    }

    public void setProject( Project project )
    {
        this.project = project;

    }

    

    private class DirectoryFileFilter implements FileFilter
    {

        @Override
        public boolean accept( File f )
        {
            try
            {
                FileObject fo = FileUtil.createData( f );
                log.info( "nme: " + fo.getName() + " ext: " + fo.getExt() );
                if ( fo.getExt().compareTo( "java" ) == 0 )
                {
                    return true;
                }
                return fo.isFolder();

            }
            catch ( IOException ex )
            {
                Exceptions.printStackTrace( ex );

            }
            return false;

        }
    }
}
